package com.example.demo.controller;

import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import com.example.demo.constant.SystemConstant;
import com.example.demo.utils.CodeUtil;
import com.example.demo.utils.MD5Util;
import com.example.demo.controller.bean.Result;
import com.example.demo.mapper.entity.Student;
import com.example.demo.service.StudentLoginService;
import com.example.demo.utils.RedisUtil;
import com.example.demo.utils.SMSUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Lucy
 * @create 2024-01-28 19:30
 */
@RequestMapping("studentLoginController")
@Api(value = "学生登录接口", tags = {"学生登录接口"})
@Slf4j
@RestController
public class StudentLoginController {

    @Autowired
    private StudentLoginService service;

     @Autowired
    private RedisUtil redisUtil;

    @ApiOperation("学生通过账号密码登录")
    @RequestMapping(value = "passwordLogin", method = {RequestMethod.POST,  RequestMethod.GET} )
    public Result<Object> passwordLogin(@RequestBody Student loginStudent){
        Student currentStudent = new Student();
        currentStudent.setNumber(loginStudent.getNumber());
        currentStudent = service.selectStudentByNumber(currentStudent.getNumber());
        if (currentStudent == null) return Result.fail("账号不存在");
        if (SystemConstant.USER_STATUS_UNAUTHORIZED == currentStudent.getState()) {
            return Result.fail("账号未通过学生认证，请前往认证或等待管理员审核");
        }
        if (SystemConstant.USER_STATUS_DISABLE == currentStudent.getState()) {
            return Result.fail("账号已被禁用，请联系管理员解封");
        }
        int errorNum = 0;
        String key = SystemConstant.userState + ":" + currentStudent.getNumber();
        if (redisUtil.hasKey(key)) {
            errorNum = (int) redisUtil.get(key);
        }
        if (errorNum >= SystemConstant.passwordErrorNum)
            return Result.fail("此账号因密码错误次数太对，已经被暂时禁用。");
        if (!MD5Util.encryptPassword(loginStudent.getPassword()).equals(currentStudent.getPassword())){
            long time = SystemConstant.passwordErrorNum_Time;
            redisUtil.set(key, errorNum + 1, time);
            return Result.fail("密码错误");
        }
        if (errorNum > 0) redisUtil.del(key);
        // 会话登录，参数填登录人的账号id
        StpUtil.login(currentStudent.getId(),new SaLoginModel().setTimeout(SystemConstant.studentLoginToken_Time));
        String token = StpUtil.getTokenValue();
        String tokenName = SaManager.getConfig().getTokenName();
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("tokenName", tokenName);
        map.put("studentNumber", currentStudent.getNumber());
        //0为男，1为女
        map.put("gender", currentStudent.getGender());
        return Result.ok("登录成功",map);
    }

    @ApiOperation("学生通过手机号获取验证码")
    @RequestMapping(value = "getCodeByPhone", method = {RequestMethod.POST,  RequestMethod.GET} )
    public Result<Object> getCodeByPhone(@RequestParam("phone")String phone){
        Student currentStudent = new Student();
        currentStudent.setPhone(phone);
        currentStudent = service.selectStudentByPhone(currentStudent.getPhone());
        if (currentStudent == null) return Result.fail("账号不存在");
        if (SystemConstant.USER_STATUS_UNAUTHORIZED == currentStudent.getState()) {
            return Result.fail("账号未通过学生认证，请前往认证或等待管理员审核");
        }
        if (SystemConstant.USER_STATUS_DISABLE == currentStudent.getState()) {
            return Result.fail("账号已被禁用，请联系管理员解封");
        }
        String code = CodeUtil.generateCode(6);
        String key = "PHONECODE" + ":" + currentStudent.getPhone();
        long time = SystemConstant.codeExpiration_Time;
        redisUtil.set(key, code, time);
        SMSUtil.sendCode(phone, code);
        return Result.ok("验证码已发送");
    }

    @ApiOperation("学生通过手机号验证码登录")
    @RequestMapping(value = "codeLogin", method = {RequestMethod.POST,  RequestMethod.GET} )
    public Result<Object> codeLogin(@RequestBody Student loginStudent){
        Student currentStudent = new Student();
        currentStudent.setPhone(loginStudent.getPhone());
        currentStudent = service.selectStudentByPhone(currentStudent.getPhone());
        int errorNum = 0;
        String key = SystemConstant.userState + ":" + currentStudent.getPhone();
        if (redisUtil.hasKey(key)) {
            errorNum = (int) redisUtil.get(key);
        }
        if (errorNum >= SystemConstant.codeErrorNum)
            return Result.fail("此账号因验证码错误次数太对，已经被暂时禁用。");
        String codeKey = "PHONECODE" + ":" + currentStudent.getPhone();
        String code = "";
        if (redisUtil.hasKey(codeKey)) {
            code = (String) redisUtil.get(codeKey);
        }else{
            return Result.fail("验证码已过期，请重新获取验证码");
        }
        if (!loginStudent.getPhoneCode().equals(code)){
            long time = SystemConstant.codeErrorNum_Time;
            redisUtil.set(key, errorNum + 1, time);
            return Result.fail("验证码错误");
        }
        if (errorNum > 0) redisUtil.del(key);
        // 会话登录，参数填登录人的账号id
        StpUtil.login(currentStudent.getId(),new SaLoginModel().setTimeout(SystemConstant.studentLoginToken_Time));
        String token = StpUtil.getTokenValue();
        String tokenName = SaManager.getConfig().getTokenName();
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("tokenName", tokenName);
        map.put("studentNumber", currentStudent.getNumber());
        //0为男，1为女
        map.put("gender", currentStudent.getGender());
        return Result.ok("登录成功",map);
    }

    @ApiOperation(value = "退出登录", notes = "开发中")
    @RequestMapping(value = "logout", method = {RequestMethod.POST})
    public Result<Object> logout() {
        if (StpUtil.getLoginIdDefaultNull() != null) {
            StpUtil.logout();
            return Result.ok("退出成功");
        } else{
            return Result.warn("未登录");
        }
    }
}
